﻿using CommonBehaviors.Actions;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Media;
using Action = Styx.TreeSharp.Action;

namespace BMSVMM
{
    public partial class Main : CombatRoutine
    {
        public override string Name { get { return "BM + SV + MM Hunter Routine by Pasterke"; } }
        public override WoWClass Class { get { return WoWClass.Hunter; } }

        public LocalPlayer Me { get { return StyxWoW.Me; } }
        public string LastSpell = string.Empty;

        public override Composite CombatBehavior { get { return CreateCombat(); } }
        public override Composite PreCombatBuffBehavior { get { return CreateBuffs(); } }
        public override Composite CombatBuffBehavior { get { return CreateBuffs(); } }
        public override Composite PullBehavior { get { return CreatePull(); } }
        public override Composite PullBuffBehavior { get { return CreatePullBuffs(); } }
        public override Composite RestBehavior { get { return CreateRest(); } }

        public bool isBoss { get { return IsWoWBoss(StyxWoW.Me.CurrentTarget); } }
        public bool Solo { get { return SoloOrNot(); } }
        public float MeleeRange = 3;
        public float SpellRange = 35;
        private static Stopwatch fightTimer = new Stopwatch();
        private static Stopwatch pullTimer = new Stopwatch();
        private static Stopwatch moveTimer = new Stopwatch();
        private static ulong lastGuid = 0;
        private string LastPetCall = string.Empty;
        public string usedBot { get { return BotManager.Current.Name.ToUpper(); } }
        

        WoWPoint pointNow = new WoWPoint();

        private static bool IsInGame
        {
            get { return StyxWoW.IsInGame; }
        }

        public int STEADY_FOCUS = 53220;
        public int FIRE = 82926;
        public int FEIGN_DEATH = 5384;
        public int LOCK_AND_LOAD = 56453;
        public int THRILL_OF_THE_HUNT = 34720;

        public override bool WantButton { get { return true; } }

        public override void OnButtonPress()
        {
            Form1 ConfigForm = new Form1();
            ConfigForm.ShowDialog();
        }


        public override void Initialize()
        {
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
            Updater.CheckForUpdate(UpdateSettingsBMSVMM.myPrefs.Revision);
            EventHandlers.AttachCombatLogEvent();
        }

        

        #region pulse
        public override void Pulse()
        {
            try
            {
                if (CanUseSpells() 
                    && !Me.Combat
                    && usedBot.Contains("ANGLER") 
                    && !buffExists(124036, Me) 
                    || (buffExists(124036, Me) && buffTimeLeft(124036, Me) <= 60000) 
                    && HaveFishingRaft)
                {

                    var raft = ObjectManager.GetObjectsOfType<WoWItem>().FirstOrDefault(item => item.Entry == 85500);
                    raft.Use();
                    Logging.Write("Using Angler's Fishing Raft");
                }
                if (Me.Pet != null && Me.GotAlivePet && LastPetCall != string.Empty) 
                { 
                    LastPetCall = string.Empty; 
                }
                if (Me.IsDead
                    && AutoBot)
                {
                    Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                }
                if (!Me.Combat && AllowMovement && (usedBot.Contains("QUEST") || usedBot.Contains("GRIND")))
                {
                    GetLoot();
                }
                if (buffExists(FEIGN_DEATH, Me) && AutoBot)
                {
                    Thread.Sleep(10 * 1000);
                    KeyboardManager.KeyUpDown(' ');
                }
                return;
            }
            catch { }
        }
        #endregion

        #region rest
        Composite CreateRest()
        {
            return new PrioritySelector(
                new Decorator(ret => Me.HealthPercent <= CRSettingsBMSVMM.myPrefs.eatfoodPercent
                    && (usedBot.Contains("QUEST") || usedBot.Contains("GRIND") || usedBot.Contains("GATHER"))
                    && !Me.IsDead
                    && !Me.IsGhost
                    && !Me.IsSwimming
                    && CanUseSpells(), new Action(ret => { Styx.CommonBot.Rest.Feed(); return RunStatus.Failure; }))
                );
        }
        #endregion

        #region pullbufss
        Composite CreatePullBuffs()
        {
            return new PrioritySelector(

                );
        }
        #endregion

        #region pull
        Composite CreatePull()
        {
            return new PrioritySelector(
                new Decorator(ret => buffExists(FEIGN_DEATH, Me), CreateFeignDeathBehavior()),
                
                new Decorator(ret => gotTarget && AllowMovement && Me.CurrentTarget.Distance >= 39, CreateRangeMovementBehavior()),
                new Decorator(ret => gotTarget && AllowMovement && Me.CurrentTarget.Distance <= 39 && Me.CurrentTarget.InLineOfSight && Me.IsMoving, CreateStopMovementBehavior()),
                new Decorator(ret => gotTarget && !Me.IsSafelyFacing(Me.CurrentTarget), FaceMyTarget()),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell("Misdirection")
                    && !buffExists("Misdirection", Me)
                    && !spellOnCooldown("Misdirection")
                    && SpellManager.CanCast("Misdirection"),
                                new Action(ret =>
                                {
                                    Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                                    LastSpell = "Misdirection";
                                    return RunStatus.Failure;
                                })),
                Cast("Concussive Shot", ret => gotTarget && SpellManager.HasSpell("Concussive Shot")),
                Cast("Auto Shot", ret => gotTarget)

               );
        }
        #endregion

        #region shutdown
        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }
        #endregion

        #region buffs
        Composite CreateBuffs()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                new Decorator(ret => buffExists(FEIGN_DEATH, Me), CreateFeignDeathBehavior()),
                Cast("Deterrence", ret => gotTarget && !spellOnCooldown("Deterrence") && Me.HealthPercent <= CRSettingsBMSVMM.myPrefs.deterrencePercent && CanUseSpells()),
                new Decorator(ret => CanUseSpells() && LastPetCall == string.Empty && Me.Pet == null && CRSettingsBMSVMM.myPrefs.CallPetAuto, CallPet()),
                new Decorator(ret => CanUseSpells() && LastPetCall != string.Empty && Me.Pet == null, RevivePet()),
                Cast("Mend Pet", ret => !Me.Combat
                    && StyxWoW.Me.GotAlivePet
                    && StyxWoW.Me.Pet.HealthPercent <= CRSettingsBMSVMM.myPrefs.useMendPet
                    && !StyxWoW.Me.Pet.HasAura("Mend Pet")
                    && CanUseSpells()),
                Cast("Aspect of the Hawk", ret => !StyxWoW.Me.HasAura("Aspect of the Hawk")
                    && !SpellManager.HasSpell("Aspect of the Iron Hawk")
                    && CanUseSpells()),
                Cast("Aspect of the Iron Hawk", ret => !StyxWoW.Me.HasAura("Aspect of the Iron Hawk")
                    && CanUseSpells()),
                Cast("Trap Launcher", ret => !StyxWoW.Me.HasAura("Trap Launcher")
                    && CanUseSpells()),
                new Decorator(ret => Me.Combat 
                    && Me.HealthPercent <= CRSettingsBMSVMM.myPrefs.useHealthstone
                    && nextHealthstoneAllowed <= DateTime.Now, Healthstone())
                );
        }
        #endregion

        #region Combat
        Composite CreateCombat()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                new Decorator(ret => buffExists(FEIGN_DEATH, Me), CreateFeignDeathBehavior()),
                new Decorator(ret => Me.CurrentTarget == null 
                    || Me.CurrentTarget.IsDead 
                    || (Me.CurrentTarget.IsFriendly && AutoBot), new Action(ret => { Me.ClearTarget(); return RunStatus.Failure; })),
                new Decorator(ret => CRSettingsBMSVMM.myPrefs.AutoTargeting
                    && (Me.CurrentTarget == null || Me.CurrentTarget.IsDead) 
                    && (Me.CurrentMap.IsBattleground || Me.CurrentMap.IsArena), FindBgTarget()),
                new Decorator(ret => CRSettingsBMSVMM.myPrefs.AutoPetTarget
                    && (Me.CurrentTarget == null || Me.CurrentTarget.IsDead)
                    && (!Me.CurrentMap.IsBattleground || !Me.CurrentMap.IsArena)
                    && (Me.GotAlivePet && (Me.PetInCombat || Me.PetAggro)), TakeMyPetsTarget()),
                new Decorator(ret => CRSettingsBMSVMM.myPrefs.AutoTargeting
                    && (Me.CurrentTarget == null || Me.CurrentTarget.IsDead)
                    && CRSettingsBMSVMM.myPrefs.AutoTargeting, FindTarget()),
                new Decorator(ret => gotTarget && AllowMovement && Me.CurrentTarget.Distance > 40, CreateRangeMovementBehavior()),
                new Decorator(ret => gotTarget 
                    && AllowMovement 
                    && Me.CurrentTarget.Distance <= 39 
                    && Me.IsMoving, CreateStopMovementBehavior()),
                new Decorator(ret => gotTarget && CRSettingsBMSVMM.myPrefs.AutoFacing && !Me.IsSafelyFacing(Me.CurrentTarget), FaceMyTarget()),
                new Decorator(ret => gotTarget && AllowMovement && AllowKiting && Me.CurrentTarget.Distance <= 8 && Me.CurrentTarget.InLineOfSight, MovingBackwardsToClose()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.HunterBeastMastery, BMRotation()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.HunterMarksmanship, MMRotation()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.HunterSurvival, SurvivalRotation()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.None, LowbieRotation())
                );
        }
        #endregion

        #region lowbierotation
        Composite LowbieRotation()
        {
            return new PrioritySelector(
                Cast("Revive Pet", ret => StyxWoW.Me.Pet != null && StyxWoW.Me.Pet.IsDead),
                Cast("Mend Pet", ret => StyxWoW.Me.GotAlivePet && StyxWoW.Me.Pet.HealthPercent <= CRSettingsBMSVMM.myPrefs.useMendPet && !StyxWoW.Me.Pet.HasAura("Mend Pet")),
                Cast("Arcane Shot", ret => gotTarget),
                Cast("Steady Shot", ret => gotTarget && Me.FocusPercent <= 35)
                );
        }
        #endregion

        #region create feign death behavior
        Composite CreateFeignDeathBehavior()
        {
            return new PrioritySelector(
                new Decorator(ret => gotTarget, new Action(ret =>
                {
                    Lua.DoString("StopAttack()");
                    Me.ClearTarget();
                    return RunStatus.Failure;
                })),
                new Decorator(
                    new Action(ret =>
                    {
                        return;
                    }))
                );
        }
        #endregion

        #region pause CR
        Composite PauseCR()
        {
            return new Action(ret =>
            {
                return;
            });
        }
        #endregion

        #region gotTarget
        public bool gotTarget
        {
            get
            {
                return Me.CurrentTarget != null && Me.CurrentTarget.IsAlive && Me.CurrentTarget.CanSelect && Me.CurrentTarget.Attackable;
            }
        }
        #endregion

        #region Call Pet
        Composite CallPet()
        {
            return (
                new Sequence(
                    new WaitContinue(4, ret => false, new ActionAlwaysSucceed()),
                    CreateCallPetBehavior()
                    ));
        }
        Composite CreateCallPetBehavior()
        {
            return new Action(ret =>
            {
                if (Me.Pet == null && !Me.GroupInfo.IsInRaid && !Me.IsInInstance)
                {
                    if (Me.Specialization == WoWSpec.None)
                    {
                        SpellManager.Cast("Call Pet 1");
                        Logging.Write("Call Pet 1");
                    }
                    if (Me.Specialization == WoWSpec.HunterBeastMastery)
                    {
                        SpellManager.Cast("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetBM);
                        Logging.Write("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetBM);
                    }
                    if (Me.Specialization == WoWSpec.HunterMarksmanship)
                    {
                        SpellManager.Cast("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetMM);
                        Logging.Write("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetMM);
                    }
                    if (Me.Specialization == WoWSpec.HunterSurvival)
                    {
                        SpellManager.Cast("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetSV);
                        Logging.Write("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetSV);
                    }

                    LastPetCall = "Call Pet";
                }
                if (Me.Pet == null && (Me.GroupInfo.IsInRaid || Me.IsInInstance))
                {
                    SpellManager.Cast("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetRaid);
                    Logging.Write("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetRaid);
                    LastPetCall = "Call Pet";
                }
                if (Me.Pet == null && Battlegrounds.IsInsideBattleground)
                {
                    SpellManager.Cast("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetBG);
                    Logging.Write("Call Pet " + CRSettingsBMSVMM.myPrefs.CallPetBG);
                    LastPetCall = "Call Pet";
                }
                return RunStatus.Failure;
            });
        }
        Composite RevivePet()
        {
            return (
                new Sequence(
                    new WaitContinue(4, ret => false, new ActionAlwaysSucceed()),
                        CreateRevivePetBehavior()
                    ));
        }
        Composite CreateRevivePetBehavior()
        {
            return new Action(ret =>
            {
                if (Me.Pet == null && LastPetCall == "Call Pet")
                {
                    SpellManager.Cast("Revive Pet");
                    Logging.Write("Revive Pet");
                    LastPetCall = string.Empty;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region take pets target
        Composite TakePetsTarget()
        {
            return new Action(ret =>
            {

                if (Me.Pet.CurrentTarget != null)
                {
                    Me.ClearTarget();
                    slog("Taking my Pet's Target");
                    Me.Pet.CurrentTarget.Target();
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region canusespells
        public bool CanUseSpells()
        {
            return !buffExists(FEIGN_DEATH, Me) && !Me.Mounted && !Me.IsFlying && !Me.IsDead && !Me.IsGhost && !Me.IsOnTransport && !Me.OnTaxi;
        }
        #endregion

        #region allowmovement
        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        public bool AllowFacing
        {
            get
            {
                if (CRSettingsBMSVMM.myPrefs.DisableAutoFacing
                    && (Me.CurrentMap.IsRaid || Me.CurrentMap.IsDungeon || Me.CurrentMap.IsInstance))
                {
                    return false;
                }
                if ((GetAsyncKeyState(Keys.LButton) != 0
                    && GetAsyncKeyState(Keys.RButton) != 0) ||
                    GetAsyncKeyState(Keys.W) != 0 ||
                    GetAsyncKeyState(Keys.S) != 0 ||
                    GetAsyncKeyState(Keys.D) != 0 ||
                    GetAsyncKeyState(Keys.A) != 0)
                {
                    return false;
                }
                return CRSettingsBMSVMM.myPrefs.AutoFacing;

            }
        }
        public bool AllowTargeting
        {
            get
            {
                if (CRSettingsBMSVMM.myPrefs.DisableAutoTargeting
                    && (Me.CurrentMap.IsRaid || Me.CurrentMap.IsDungeon || Me.CurrentMap.IsInstance))
                {
                    return false;
                }
                if ((GetAsyncKeyState(Keys.LButton) != 0
                    && GetAsyncKeyState(Keys.RButton) != 0) ||
                    GetAsyncKeyState(Keys.W) != 0 ||
                    GetAsyncKeyState(Keys.S) != 0 ||
                    GetAsyncKeyState(Keys.D) != 0 ||
                    GetAsyncKeyState(Keys.A) != 0)
                {
                    return false;
                }
                if (Me.CurrentMap.IsArena) { return false; }

                return CRSettingsBMSVMM.myPrefs.AutoTargeting;
            }
        }
        public bool AllowMovement
        {
            get
            {
                if (CRSettingsBMSVMM.myPrefs.DisableAutoMovement
                    && (Me.CurrentMap.IsRaid || Me.CurrentMap.IsDungeon || Me.CurrentMap.IsInstance))
                {
                    return false;
                }
                if ((GetAsyncKeyState(Keys.LButton) != 0
                    && GetAsyncKeyState(Keys.RButton) != 0) ||
                    GetAsyncKeyState(Keys.W) != 0 ||
                    GetAsyncKeyState(Keys.S) != 0 ||
                    GetAsyncKeyState(Keys.D) != 0 ||
                    GetAsyncKeyState(Keys.A) != 0)
                {
                    return false;
                }
                return CRSettingsBMSVMM.myPrefs.AutoMovement;
            }
        }
        #endregion

        #region AllowKiting
        public bool AllowKiting
        {
            get
            {
                return CRSettingsBMSVMM.myPrefs.Kiting;
            }
        }
        #endregion

        #region useitems
        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
            {
                return false;
            }


            return item.Usable && item.Cooldown <= 0;
        }
        #endregion

        #region addcount
        IEnumerable<WoWUnit> UnfriendlyUnits
        {
            get
            {
                return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => !u.IsDead
                    && u.CanSelect
                    && u.Attackable
                    && !u.IsFriendly
                    && !u.IsCritter
                    && !u.IsNonCombatPet
                    && !u.Name.Contains("Dummy")
                    && u.Location.Distance(StyxWoW.Me.CurrentTarget.Location) <= 12);
            }
        }
        #endregion

        #region spellcasting
        private delegate T Selection<out T>(object context);
        Composite Cast(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        Logging.Write(spell);
                        LastSpell = spell;
                    }
                        ));
        }
        Composite CastCallPet(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        Logging.Write(spell);
                        LastPetCall = "Call Pet";
                    }
                        ));
        }
        Composite CastRevivePet(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        Logging.Write(spell);
                        LastPetCall = string.Empty;
                    }
                        ));
        }
        Composite DropCast(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null) && SpellManager.CanCast(spell)),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        StyxWoW.SleepForLagDuration();
                        SpellManager.ClickRemoteLocation(StyxWoW.Me.Pet.Location);
                        Logging.Write(spell);
                        LastSpell = spell;

                        return RunStatus.Failure;
                    }));
        }
        Composite DropCastOnMe(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        StyxWoW.SleepForLagDuration();
                        SpellManager.ClickRemoteLocation(StyxWoW.Me.Location);
                        Logging.Write(spell);
                        LastSpell = spell;
                    }));
        }
        #endregion

        #region multi shot
        Composite CreateMultiShotBehavior()
        {
            return new PrioritySelector(
                new Decorator(
                    new Action(ret =>
                        {
                            if (gotTarget && CRSettingsBMSVMM.myPrefs.MisdirectChoice == CRSettingsBMSVMM.Misdirect.Auto
                                && SpellManager.HasSpell("Misdirection")
                                && !Me.CurrentTarget.Name.Contains("Dummy")
                                && !buffExists("Misdirection", Me)
                                && !spellOnCooldown("Misdirection")
                                && SpellManager.CanCast("Misdirection"))
                            {
                                Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                                LastSpell = "Misdirection";

                            }
                            if (gotTarget && Me.FocusPercent >= 40 && SpellManager.CanCast("Multi-Shot"))
                            {
                                SpellManager.Cast("Multi-Shot");
                                Logging.Write("Multi-Shot");
                                LastSpell = "Multi-Shot";
                            }
                            return RunStatus.Failure;
                        }))
                );
        }
        #endregion

        #region misdirection
        Composite CreateMisdirectionBehavior()
        {
            return new PrioritySelector(
                new Decorator(ret => gotTarget && CRSettingsBMSVMM.myPrefs.MisdirectChoice == CRSettingsBMSVMM.Misdirect.Auto
                    && !buffExists("Misdirection", Me)
                    && !Me.CurrentTarget.Name.Contains("Dummy")
                    && !spellOnCooldown("Misdirection")
                    && StyxWoW.Me.CurrentTarget.ThreatInfo.RawPercent >= 90,
                                new Action(ret =>
                                {
                                    if (SpellManager.CanCast("Misdirection"))
                                    {
                                        Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                                        LastSpell = "Misdirection";
                                    }
                                    return RunStatus.Failure;
                                }))
                );
        }
        #endregion

        #region Kind of target
        public bool IsWoWBoss(WoWUnit mytarget)
        {
            if (StyxWoW.Me.CurrentTarget != null)
            {
                if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.WorldBoss)
                {
                    return true;
                }
                else if (target.IsBoss(mytarget))
                {
                    return true;
                }
                else if (Me.CurrentTarget.MaxHealth >= (100 * 1000000)) { return true; }
                else if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.RareElite
                    && StyxWoW.Me.CurrentTarget.MaxHealth >= (StyxWoW.Me.MaxHealth * CRSettingsBMSVMM.myPrefs.CooldownElites)
                    && (!StyxWoW.Me.GroupInfo.IsInParty
                    || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                    && !StyxWoW.Me.GroupInfo.IsInRaid
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Rare
                    && StyxWoW.Me.CurrentTarget.MaxHealth >= (StyxWoW.Me.MaxHealth * CRSettingsBMSVMM.myPrefs.CooldownElites)
                    && (!StyxWoW.Me.GroupInfo.IsInParty
                    || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                    && !StyxWoW.Me.GroupInfo.IsInRaid
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Elite
                    && StyxWoW.Me.CurrentTarget.MaxHealth >= (StyxWoW.Me.MaxHealth * CRSettingsBMSVMM.myPrefs.CooldownElites)
                    && (!StyxWoW.Me.GroupInfo.IsInParty
                    || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                    && !StyxWoW.Me.GroupInfo.IsInRaid
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.Name.Contains("Dummy")
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.IsPlayer
                    && !StyxWoW.Me.CurrentTarget.IsFriendly)
                {
                    return true;
                }
            }
            return false;
        }
        #endregion Kind of Target

        #region pause
        public static bool PauseAoe = false;
        public static bool Paused = false;
        private static bool BurstEnabled = false;

        public static void HandleModifierStateChanged(object sender, LuaEventArgs args)
        {
            if (CRHotKeySettings.myPrefs.StopCRKey == CRHotKeySettings.Keypress.NONE
                && CRHotKeySettings.myPrefs.StopAoeKey == CRHotKeySettings.Keypress.NONE
                && CRHotKeySettings.myPrefs.BurstKey == CRHotKeySettings.Keypress.NONE)
            {
                return;
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                string pauseMyAoe = "AOE cancelled, press " + CRHotKeySettings.myPrefs.StopAoeKey.ToString() + " in WOW again to turn AOE back on";
                if (args.Args[0].ToString() == CRHotKeySettings.myPrefs.StopAoeKey.ToString())
                {
                    PauseAoe = !PauseAoe;
                    if (PauseAoe)
                    {
                        Logging.Write("Aoe cancelled, press {0} in WOW again to resume Aoe",
                                     CRHotKeySettings.myPrefs.StopAoeKey.ToString());
                        if (CRHotKeySettings.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"" + pauseMyAoe + "\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("Aoe Resumed");
                        if (CRHotKeySettings.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Aoe Resumed !\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == CRHotKeySettings.myPrefs.StopCRKey.ToString())
                {
                    string pauseCR = "CR paused, press " + CRHotKeySettings.myPrefs.StopCRKey.ToString() + " in WOW again to turn back on";
                    Paused = !Paused;
                    if (Paused)
                    {
                        Logging.Write("CR paused, press {0} in WOW again to turn back on",
                                     CRHotKeySettings.myPrefs.StopCRKey.ToString());
                        if (CRHotKeySettings.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"" + pauseCR + "\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("CR running again ....");
                        if (CRHotKeySettings.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"CR running again ....\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == CRHotKeySettings.myPrefs.BurstKey.ToString())
                {
                    string pauseCR = "Burstkey enabled, press " + CRHotKeySettings.myPrefs.BurstKey.ToString() + " in WoW to disable it again";
                    BurstEnabled = !BurstEnabled;
                    if (BurstEnabled)
                    {
                        Logging.Write("Burstkey enabled, press {0} in WOW again to turn back off",
                                     CRHotKeySettings.myPrefs.StopCRKey.ToString());
                        if (CRHotKeySettings.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"" + pauseCR + "\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("Burstkey Disabled");
                        if (CRHotKeySettings.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Burstkey Disabled\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
        }
        #endregion pause

        #region solo or not
        public bool SoloOrNot()
        {
            return (!StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                && !StyxWoW.Me.GroupInfo.IsInRaid
                && !StyxWoW.Me.IsInInstance
                && !Me.CurrentTarget.Name.Contains("Dummy");
        }
        #endregion

        #region explotrap
        public bool useExplosiveTrap()
        {
            string trap = CRSettingsBMSVMM.myPrefs.useExploTrap.ToString();
            switch (trap)
            {
                case "Never":
                    return false;
                case "Always":
                    return true;
                case "BossOnly":
                    if (isBoss) { return true; }
                    return false;
                default:
                    return false;
            }
        }
        Composite ExploTrapSingle()
        {
            return new Decorator(ret => gotTarget
                && SpellManager.HasSpell("Trap Launcher")
                && useExplosiveTrap() && buffExists("Trap Launcher", Me)
                && !spellOnCooldown("Explosive Trap")
                && LastSpell != "Explosive Trap",
                new Action(ret =>
                {
                    if (SpellManager.CanCast("Explosive Trap"))
                    {
                        SpellManager.Cast("Explosive Trap");
                        SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
                        Logging.Write(Colors.LightBlue, "Explosive Trap Single Target");
                        LastSpell = "Explosive Trap";
                    }
                    return RunStatus.Failure;
                }));
        }
        Composite ExploTrapMulti()
        {
            return new Decorator(ret => gotTarget
                && SpellManager.HasSpell("Trap Launcher")
                && buffExists("Trap Launcher", Me)
                && !spellOnCooldown("Explosive Trap")
                && LastSpell != "Explosive Trap",
                new Action(ret =>
                {
                    if (SpellManager.CanCast("Explosive Trap"))
                    {
                        SpellManager.Cast("Explosive Trap");
                        SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
                        Logging.Write(Colors.LightBlue, "Explosive Trap");
                        LastSpell = "Explosive Trap";
                    }
                    return RunStatus.Failure;
                }));
        }
        Composite SnakeTrap()
        {
            return new Decorator(ret => gotTarget
                && SpellManager.HasSpell("Trap Launcher")
                && buffExists("Trap Launcher", Me)
                && !spellOnCooldown("Snake Trap")
                && LastSpell != "Snake Trap",
                new Action(ret =>
                {
                    if (SpellManager.CanCast("Snake Trap"))
                    {
                        SpellManager.Cast("Snake Trap");
                        SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
                        Logging.Write(Colors.LightBlue, "Snake Trap");
                        LastSpell = "Snake Trap";
                    }
                    return RunStatus.Failure;
                }));
        }
        #endregion

        #region talents
        Composite CreateTalent60Behavior()
        {
            return new PrioritySelector(
                new Decorator(
                    new Action(ret =>
                    {
                        if (CRSettingsBMSVMM.myPrefs.useTalent60 == CRSettingsBMSVMM.Talent60.Dire_Beast)
                        {
                            if (gotTarget && !spellOnCooldown("Dire Beast") && SpellManager.CanCast("Dire Beast"))
                            {
                                SpellManager.Cast("Dire Beast");
                                slog("Dire Beast");
                                LastSpell = "Dire Beast";
                            }
                        }
                        if (CRSettingsBMSVMM.myPrefs.useTalent60 == CRSettingsBMSVMM.Talent60.Fervor)
                        {
                            if (gotTarget && !spellOnCooldown("Fervor") && Me.FocusPercent <= CRSettingsBMSVMM.myPrefs.useTalent60Focus && SpellManager.CanCast("Fervor"))
                            {
                                SpellManager.Cast("Fervor");
                                slog("Fervor");
                                LastSpell = "Fervor";
                            }
                        }
                        return RunStatus.Failure;
                    }))
                );
        }
        Composite CreateTalent75Behavior()
        {
            return new PrioritySelector(
                new Decorator(
                    new Action(ret =>
                    {
                        if (CRSettingsBMSVMM.myPrefs.useTalent75 == CRSettingsBMSVMM.Talent75.A_Murder_of_Crows
                            && (!BurstKeySettings.myPrefs.useBurstMode || (BurstKeySettings.myPrefs.useBurstMode && !BurstKeySettings.myPrefs.useBurstCrows)))
                        {
                            if (gotTarget && isBoss && !spellOnCooldown("A Murder of Crows") && SpellManager.CanCast("A Murder of Crows"))
                            {
                                SpellManager.Cast("A Murder of Crows");
                                slog("A Murder of Crows");
                                LastSpell = "A Murder of Crows";
                            }
                        }
                        if (CRSettingsBMSVMM.myPrefs.useTalent75 == CRSettingsBMSVMM.Talent75.Lynx_Rush)
                        {
                            if (gotTarget && !spellOnCooldown("Lynx Rush") && SpellManager.CanCast("Lynx Rush"))
                            {
                                SpellManager.Cast("Lynx Rush");
                                slog("Lynx Rush");
                                LastSpell = "Lynx Rush";
                            }
                        }
                        return RunStatus.Failure;
                    }))
                );
        }
        Composite CreateTalent90Behavior()
        {
            return new PrioritySelector(
                new Decorator(
                    new Action(ret =>
                        {
                            if (CRSettingsBMSVMM.myPrefs.useTalent90 == CRSettingsBMSVMM.Talent90.Glaive_Toss)
                            {
                                if (gotTarget && !spellOnCooldown("Glaive Toss") && SpellManager.CanCast("Glaive Toss"))
                                {
                                    if (SpellManager.HasSpell("Misdirection") && CRSettingsBMSVMM.myPrefs.MisdirectChoice == CRSettingsBMSVMM.Misdirect.Auto
                                        && !Me.CurrentTarget.Name.Contains("Dummy")
                                        && !buffExists("Misdirection", Me)
                                        && !spellOnCooldown("Misdirection")
                                        && SpellManager.CanCast("Misdirection"))
                                    {
                                        Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                                        LastSpell = "Misdirection";

                                    }
                                    SpellManager.Cast("Glaive Toss");
                                    slog("Glaive Toss");
                                    LastSpell = "Glaive Toss";
                                }
                            }
                            if (CRSettingsBMSVMM.myPrefs.useTalent90 == CRSettingsBMSVMM.Talent90.Powershot)
                            {
                                if (gotTarget && !spellOnCooldown("Powershot") && SpellManager.CanCast("Powershot"))
                                {
                                    if (SpellManager.HasSpell("Misdirection") && CRSettingsBMSVMM.myPrefs.MisdirectChoice == CRSettingsBMSVMM.Misdirect.Auto
                                        && !Me.CurrentTarget.Name.Contains("Dummy")
                                        && !buffExists("Misdirection", Me)
                                        && !spellOnCooldown("Misdirection")
                                        && SpellManager.CanCast("Misdirection"))
                                    {
                                        Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                                        LastSpell = "Misdirection";

                                    }
                                    SpellManager.Cast("Powershot");
                                    slog("Powershot");
                                    LastSpell = "Powershot";
                                }
                            }
                            if (CRSettingsBMSVMM.myPrefs.useTalent90 == CRSettingsBMSVMM.Talent90.Barrage)
                            {
                                if (gotTarget && !spellOnCooldown("Barrage") && SpellManager.CanCast("Barrage"))
                                {
                                    if (SpellManager.HasSpell("Misdirection") && CRSettingsBMSVMM.myPrefs.MisdirectChoice == CRSettingsBMSVMM.Misdirect.Auto
                                        && !Me.CurrentTarget.Name.Contains("Dummy")
                                        && !buffExists("Misdirection", Me)
                                        && !spellOnCooldown("Misdirection")
                                        && SpellManager.CanCast("Misdirection"))
                                    {
                                        Lua.DoString("RunMacroText('/cast [@focus,help][help][@pet,exists] Misdirection');");
                                        LastSpell = "Misdirection";

                                    }
                                    SpellManager.Cast("Barrage");
                                    slog("Barrage");
                                    LastSpell = "Barrage";
                                }
                            }
                            return RunStatus.Failure;

                        }))
                );
        }
        #endregion
    }
}
